//
//  ZRWebViewController.m
//  简书:https://www.jianshu.com/u/043e94ca450f
//
//  Created by 黄涛 on 2018/10/22.
//  Copyright © 2018年 zero. All rights reserved.
//

#import "ZRWebViewController.h"
#import <WebKit/WebKit.h>
@interface ZRWebViewController ()<WKUIDelegate,WKNavigationDelegate,WKScriptMessageHandler>

@property (nonatomic , strong) WKWebView * webView;
@property (nonatomic , strong) UIProgressView * progressView;

@property (nonatomic , weak) WKUserContentController * userContentCtrler;

@end

static void *WKWebBrowserContext = &WKWebBrowserContext;
static NSString * const name_JSMessage = @"ZRWebViewCtrler";
@implementation ZRWebViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self.view addSubview:self.webView];
    [self.view addSubview:self.progressView];
    [self loadData];
    
}



#pragma mark - ----------------------- 生命周期 -----------------------
#pragma mark - ----------------------- 其他方法 -----------------------

- (void)loadData{
    
    if (self.urlStr.hash) {
       NSURL * url = [NSURL URLWithString:self.urlStr relativeToURL:[NSURL URLWithString:@"https://"]];
        NSURLRequest * request = [NSURLRequest requestWithURL:url];
        [self.webView loadRequest:request];
        return;
    }
    
    if (self.htmlStr.hash) {
        [self.webView loadHTMLString:self.htmlStr baseURL:nil];
        return;
    }
    
}


/** 给JS发送消息 */
- (void)sendToJS:(NSString *)jsMethod complete:(void (^)(id _Nullable response))complete{
    
    [self.webView evaluateJavaScript:jsMethod completionHandler:^(id _Nullable response, NSError * _Nullable error) {
        
        !complete ? : complete(response);
        
    }];
    
}
#pragma mark - ----------------------- 代理方法 -----------------------
#pragma mark - WKNavigation Delegate
/** 开始加载 */
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
    
    self.progressView.hidden = NO;

}

/** 网页加载完成 */
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
    
    self.progressView.hidden = YES;
    self.navigationItem.title = webView.title;
    NSLog(@"网页 标题 : %@",webView.title);
}

#pragma mark - WKScriptMessageHandler Delegate
/** 拦截执行网页中的JS方法 */
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
    
    //服务器写法: window.webkit.messageHandlers.名字.postMessage(内容);
    //客户端写法: [message.name isEqualToString:@"名称"];
    
    !_jsBackWithBodyBlock ? : self.jsBackWithBodyBlock(message.body , message.name);
}


#pragma mark - ----------------------- 活动监听 -----------------------
/** KVO 监听进度条 */
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    
    if ([keyPath isEqualToString:NSStringFromSelector(@selector(estimatedProgress))] && object == self.webView) {
        
        [self.progressView setAlpha:1.0f];
        BOOL animated = self.webView.estimatedProgress > self.progressView.progress;
        [self.progressView setProgress:self.webView.estimatedProgress animated:animated];
        
        if (self.webView.estimatedProgress >= 1.0f) {
            
            [UIView animateWithDuration:0.3f delay:0.3f options:UIViewAnimationOptionCurveEaseOut animations:^{
                [self.progressView setAlpha:0.0f];
            } completion:^(BOOL finished) {
                [self.progressView setProgress:0.0f animated:NO];
            }];
        }
        
        
    }else{
        
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
        
    }
    
    
    
}


#pragma mark - ---------------------- set & get ----------------------
- (WKWebView *)webView{
    if (!_webView) {
        
        //自定义配置，一般用于js调用OC方法（OC拦截URL中的数据做自定义操作）
        WKUserContentController * userContentCtrler = [[WKUserContentController alloc] init];
        //添加消息处理，注意 sele纸袋的对象需要遵守WKScriptMessageHandle 协议，结束时要移除
        [userContentCtrler addScriptMessageHandler:self name:name_JSMessage];
        _userContentCtrler = userContentCtrler;
        
        WKWebViewConfiguration * configuration = [[WKWebViewConfiguration alloc] init];
        //允许与网页交互 选择视图
        configuration.selectionGranularity = YES;
        //web 内容处理池
        configuration.processPool = [[WKProcessPool alloc] init];
        //是否支持记忆读取
        configuration.suppressesIncrementalRendering = YES;
        //允许用户更改网页设置
        configuration.userContentController = userContentCtrler;
        
        _webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, ZRNavBarHeight, self.view.width, self.view.height - ZRNavBarHeight) configuration:configuration];
        _webView.backgroundColor = ZRSameRGBColor(240);
        _webView.navigationDelegate = self;
        _webView.UIDelegate = self;
        [_webView addObserver:self forKeyPath:NSStringFromSelector(@selector(estimatedProgress)) options:0 context:WKWebBrowserContext];

        [_webView sizeToFit];
        
        // 此处一定要做判断，因为是iOS9之后才有的方法，否则在iOS8下会崩溃
        if ([[UIDevice currentDevice].systemVersion floatValue] >= 9.0) {
            //允许视频播放
            configuration.allowsAirPlayForMediaPlayback = YES;
            // 允许在线播放
            configuration.allowsInlineMediaPlayback = YES;
            //开启手势触摸 默认设置就是NO。在ios8系统中会导致手势问题，程序崩溃
            _webView.allowsBackForwardNavigationGestures = YES;
        }
    
    }
    return _webView;
}

- (UIProgressView *)progressView{
    if (!_progressView) {
        _progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
        _progressView.frame = CGRectMake(0, ZRNavBarHeight, self.view.width, 3);
        _progressView.progressTintColor = [UIColor redColor];
        _progressView.trackTintColor = [UIColor grayColor];        
    }
    
    return _progressView;
}


#pragma mark - ---------------------- 释放 ----------------------
- (void)dealloc{
    
    [self.webView removeObserver:self forKeyPath:NSStringFromSelector(@selector(estimatedProgress))];

    [self.userContentCtrler removeScriptMessageHandlerForName:name_JSMessage];
}



- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}





@end
